home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / ungepackte_daten / 1994 / 8 / 05 / term-4.0-source.lha / termXPR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  52.4 KB  |  2,519 lines

  1. /*
  2. **    termXPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12. /*#define WriteRequest ReadRequest*/
  13.  
  14.     /* These variables keep the transferred bytes and transfer
  15.      * time in seconds.
  16.      */
  17.  
  18. STATIC LONG         ByteVal,
  19.              ByteMax,
  20.              TimeVal,
  21.              TimeMax,
  22.  
  23.              LastTimeDif,
  24.              LastPercent;
  25.  
  26.     /* Transfer statistics. */
  27.  
  28. STATIC ULONG         CPS_Minimum,
  29.              CPS_Maximum,
  30.              CPS_Average,
  31.              CPS_Current,
  32.              CPS_Count,
  33.              CPS_Last;
  34.  
  35.     LONG         CPL_Min,
  36.              CPL_Avg,
  37.              CPL_Cur;
  38.  
  39.     /* The name of the file being transmitted, in case the
  40.      * `override transfer path' feature is enabled.
  41.      */
  42.  
  43. STATIC struct Buffer    *CurrentFile;
  44.  
  45.     /* Yet another flag, this one determines whether we already told
  46.      * the user that the file we are currently processing will fit
  47.      * on the destination device.
  48.      */
  49.  
  50. STATIC BYTE         Alerted,
  51.              CarrierMessage;
  52.  
  53. STATIC UBYTE __far     RealName[MAX_FILENAME_LENGTH];
  54. STATIC ULONG         LastSeconds;
  55.  
  56.     /* PrintBox(LONG Box,LONG Line,STRPTR String,...):
  57.      *
  58.      *    Update the contents of a text box.
  59.      */
  60.  
  61. STATIC VOID __stdargs
  62. PrintBox(LONG Box,LONG Line,STRPTR String,...)
  63. {
  64.     UBYTE     LocalBuffer[256];
  65.     va_list     VarArgs;
  66.  
  67.     va_start(VarArgs,String);
  68.     VSPrintf(LocalBuffer,String,VarArgs);
  69.     va_end(VarArgs);
  70.  
  71.     LT_SetAttributes(TransferHandle,Box,LABX_Index,Line,LABX_Text,LocalBuffer,TAG_DONE);
  72. }
  73.  
  74.     /* OpenTransferWindow():
  75.      *
  76.      *    Local routine to open the transfer window.
  77.      */
  78.  
  79. STATIC BYTE
  80. OpenTransferWindow(VOID)
  81. {
  82.         /* Block window input. */
  83.  
  84.     BlockWindows();
  85.  
  86.         /* Try to open the transfer window panel. */
  87.  
  88.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  89.     {
  90.             /* Supply the log text. */
  91.  
  92.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  93.  
  94.             /* Return success. */
  95.  
  96.         return(TRUE);
  97.     }
  98.     else
  99.     {
  100.             /* Re-enable window input. */
  101.  
  102.         ReleaseWindows();
  103.  
  104.             /* Return failure. */
  105.  
  106.         return(FALSE);
  107.     }
  108. }
  109.  
  110.     /* CheckAbort(BOOLEAN CheckCarrier):
  111.      *
  112.      *    Check for transfer abort.
  113.      */
  114.  
  115. STATIC LONG __regargs
  116. CheckAbort(BOOLEAN CheckCarrier)
  117. {
  118.     struct IntuiMessage    *Message;
  119.     ULONG             MsgClass,
  120.                  MsgQualifier;
  121.     UWORD             MsgCode;
  122.     struct Gadget        *MsgGadget;
  123.     struct Window        *MsgWindow;
  124.     LONG             Result = 0;
  125.  
  126.         /* No window available for output? */
  127.  
  128.     if(!TransferWindow)
  129.     {
  130.         if(!OpenTransferWindow())
  131.             return(-1);
  132.     }
  133.  
  134.         /* Are we to check the carrier status? */
  135.  
  136.     if(CheckCarrier)
  137.     {
  138.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  139.  
  140.         DoIO(WriteRequest);
  141.  
  142.             /* Return error if carrier is lost. */
  143.  
  144.         if(WriteRequest -> io_Status & CIAF_COMCD)
  145.         {
  146.             if(!CarrierMessage)
  147.             {
  148.                 CarrierMessage = TRUE;
  149.  
  150.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  151.             }
  152.  
  153.             Online = FALSE;
  154.  
  155.             TransferError = TRUE;
  156.  
  157.             return(-1);
  158.         }
  159.     }
  160.  
  161.         /* Process all incoming messages. */
  162.  
  163.     while(Message = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  164.     {
  165.         MsgClass    = Message -> Class;
  166.         MsgQualifier    = Message -> Qualifier;
  167.         MsgCode        = Message -> Code;
  168.         MsgGadget    = (struct Gadget *)Message -> IAddress;
  169.         MsgWindow    = Message -> IDCMPWindow;
  170.  
  171.         GT_ReplyIMsg(Message);
  172.  
  173.         if(MsgWindow == TransferWindow)
  174.         {
  175.             LT_HandleInput(TransferHandle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  176.  
  177.             if(!Result)
  178.             {
  179.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  180.                 {
  181.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  182.  
  183.                     TransferAborted = TRUE;
  184.  
  185.                     Result = -1;
  186.                 }
  187.  
  188.                 if(MsgClass == IDCMP_GADGETUP)
  189.                 {
  190.                     switch(MsgGadget -> GadgetID)
  191.                     {
  192.                         case GAD_TRANSFER_ABORT:
  193.  
  194.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  195.  
  196.                             TransferAborted = TRUE;
  197.  
  198.                             Result = -1;
  199.  
  200.                             break;
  201.  
  202.                         case GAD_TRANSFER_SKIP:
  203.  
  204.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  205.  
  206.                             Result = 1;
  207.  
  208.                             break;
  209.  
  210.                         case GAD_TRANSFER_ABORT_FILE:
  211.  
  212.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_ABORTED_TXT));
  213.  
  214.                             Result = 2;
  215.  
  216.                             break;
  217.                     }
  218.                 }
  219.             }
  220.         }
  221.         else
  222.         {
  223.             if(TransferPerfWindow)
  224.             {
  225.                 struct RastPort *RPort = TransferPerfWindow -> RPort;
  226.  
  227.                 if(MsgClass == IDCMP_NEWSIZE)
  228.                 {
  229.                     SetAPen(RPort,0);
  230.  
  231.                     RectFill(RPort,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  232.  
  233.                     CPL_Min = CPL_Avg = CPL_Cur = -1;
  234.                 }
  235.  
  236.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  237.                 {
  238.                     PutWindowInfo(WINDOW_PERF,TransferPerfWindow -> LeftEdge,TransferPerfWindow -> TopEdge,TransferPerfWindow -> Width,TransferPerfWindow -> Height);
  239.  
  240.                     CloseWindowSafely(TransferPerfWindow);
  241.  
  242.                     TransferPerfWindow = NULL;
  243.                 }
  244.             }
  245.         }
  246.     }
  247.  
  248.     return(Result);
  249. }
  250.  
  251.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  252.      *
  253.      *    Build a valid file and path name, including path
  254.      *    substitution, etc.
  255.      */
  256.  
  257. STATIC STRPTR __regargs
  258. NewFileName(STRPTR Source,STRPTR Buffer)
  259. {
  260.     if(Config -> MiscConfig -> OverridePath && !Uploading)
  261.     {
  262.         if(DownloadPath)
  263.             strcpy(Buffer,DownloadPath);
  264.         else
  265.             strcpy(Buffer,Config -> PathConfig -> BinaryDownloadPath);
  266.  
  267.         if(!Buffer[0])
  268.         {
  269.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  270.                 Buffer[0] = 0;
  271.         }
  272.  
  273.         if(Buffer[0])
  274.         {
  275.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  276.                 return(Buffer);
  277.         }
  278.     }
  279.     else
  280.     {
  281.         if(FilePart(Source) == Source)
  282.         {
  283.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  284.             {
  285.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  286.                     return(Buffer);
  287.             }
  288.         }
  289.     }
  290.  
  291.     strcpy(Buffer,Source);
  292.  
  293.     return(Source);
  294. }
  295.  
  296.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  297.      *
  298.      *    Attach source information (BBS name, date and time) to a file.
  299.      */
  300.  
  301. STATIC VOID __regargs
  302. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  303. {
  304.     UBYTE        LocalBuffer[MAX_FILENAME_LENGTH],
  305.             Time[40],
  306.             Date[40];
  307.     struct DateTime    DateTime;
  308.  
  309.     CopyMem(OpenDate,&DateTime . dat_Stamp,sizeof(struct DateStamp));
  310.  
  311.         /* Prepare for date conversion. */
  312.  
  313.     DateTime . dat_Format    = FORMAT_DOS;
  314.     DateTime . dat_Flags    = 0;
  315.     DateTime . dat_StrDay    = NULL;
  316.     DateTime . dat_StrDate    = Date;
  317.     DateTime . dat_StrTime    = Time;
  318.  
  319.         /* Convert the date. */
  320.  
  321.     if(DateToStr(&DateTime))
  322.     {
  323.         StripSpaces(BBSName);
  324.         StripSpaces(Date);
  325.         StripSpaces(Time);
  326.  
  327.         if(BBSName[0])
  328.             SPrintf(LocalBuffer,"%s %s %s",BBSName,Date,Time);
  329.         else
  330.             SPrintf(LocalBuffer,"%s %s",Date,Time);
  331.  
  332.         SetComment(Name,LocalBuffer);
  333.     }
  334. }
  335.  
  336.     /* GetSeconds(STRPTR String):
  337.      *
  338.      *    Tries to turn a string of the format hh:mm:ss into
  339.      *    an integer number.
  340.      */
  341.  
  342. STATIC LONG __regargs
  343. GetSeconds(STRPTR String)
  344. {
  345.     UBYTE    Buffer[20];
  346.     LONG    Seconds = 0;
  347.  
  348.     memset(Buffer,0,20);
  349.  
  350.     strcpy(Buffer,String);
  351.  
  352.     Seconds += Atol(&Buffer[6]);
  353.  
  354.     Buffer[5] = 0;
  355.  
  356.     Seconds += Atol(&Buffer[3]) * 60;
  357.  
  358.     Buffer[2] = 0;
  359.  
  360.     Seconds += Atol(&Buffer[0]) * 3600;
  361.  
  362.     return(Seconds);
  363. }
  364.  
  365.     /* TruncateName(STRPTR FileName):
  366.      *
  367.      *    Truncates a file name to a maximum of 48 characters.
  368.      */
  369.  
  370. STATIC STRPTR __regargs
  371. TruncateName(STRPTR FileName)
  372. {
  373.     WORD Len = strlen(FileName);
  374.  
  375.     if(Len > 48)
  376.     {
  377.         WORD i;
  378.  
  379.         for(i = Len - 48 ; i < Len ; i++)
  380.         {
  381.             if(i >= Len - 44 && FileName[i] == '/')
  382.             {
  383.                 STATIC UBYTE __far NameBuffer[MAX_FILENAME_LENGTH];
  384.  
  385.                 strcpy(NameBuffer,".../");
  386.  
  387.                 strcat(NameBuffer,&FileName[i + 1]);
  388.  
  389.                 return(NameBuffer);
  390.             }
  391.         }
  392.     }
  393.  
  394.     return(FileName);
  395. }
  396.  
  397.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  398.      *
  399.      *    Calculate the number of blocks a file will
  400.      *    occupy if saved to a disk.
  401.      */
  402.  
  403. STATIC LONG __regargs
  404. CalculateBlocks(LONG Size,LONG BlockSize)
  405. {
  406.     LONG    Blocks        = 1;        /* One for the file header. */
  407.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  408.         Extension    = 0;        /* How many block pointers yet. */
  409.  
  410.         /* Round to next block. */
  411.  
  412.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  413.  
  414.     while(Size)
  415.     {
  416.             /* Add another block. */
  417.  
  418.         Blocks++;
  419.  
  420.             /* Subtract another block. */
  421.  
  422.         Size -= BlockSize;
  423.  
  424.             /* Add another block pointer, if 72 have been
  425.              * added, add another extension block.
  426.              */
  427.  
  428.         if((Extension++) == 72)
  429.         {
  430.                 /* If no extension block has been generated
  431.                  * yet, we were running on the block pointers
  432.                  * of the file header itself.
  433.                  */
  434.  
  435.             if(!HasExtension)
  436.                 HasExtension = TRUE;
  437.             else
  438.                 Blocks++;
  439.  
  440.                 /* Reset extension block counter. */
  441.  
  442.             Extension = 0;
  443.         }
  444.     }
  445.  
  446.     return(Blocks);
  447. }
  448.  
  449.     /* GetOptionMode(struct xpr_option *Option):
  450.      *
  451.      *    Turn text into a boolean value.
  452.      */
  453.  
  454. STATIC BYTE __regargs
  455. GetOptionMode(struct xpr_option *Option)
  456. {
  457.     if(Option)
  458.     {
  459.         STATIC STRPTR TrueOptions[] =
  460.         {
  461.             "ON",
  462.             "TRUE",
  463.             "T",
  464.             "YES",
  465.             "Y",
  466.             NULL
  467.         };
  468.  
  469.         register WORD i;
  470.  
  471.         for(i = 0 ; TrueOptions[i] ; i++)
  472.         {
  473.             if(!Stricmp(Option -> xpro_value,TrueOptions[i]))
  474.                 return(TRUE);
  475.         }
  476.     }
  477.  
  478.     return(FALSE);
  479. }
  480.  
  481.     /* SerialErrorReport(struct IOExtSer *Request):
  482.      *
  483.      *    Report a certain I/O error cause.
  484.      */
  485.  
  486. STATIC BYTE __regargs
  487. SerialErrorReport(struct IOExtSer *Request)
  488. {
  489.     STRPTR    ErrorMessage;
  490.     BYTE    IsFatal;
  491.  
  492.     switch(Request -> IOSer . io_Error)
  493.     {
  494.         case SerErr_LineErr:
  495.  
  496.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_HARDWARE_DATA_OVERRUN_TXT);
  497.  
  498.             IsFatal = FALSE;
  499.  
  500.             break;
  501.  
  502.         case SerErr_ParityErr:
  503.  
  504.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_PARITY_ERROR_TXT);
  505.  
  506.             IsFatal = TRUE;
  507.  
  508.             break;
  509.  
  510.         case SerErr_TimerErr:
  511.  
  512.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_TIMER_ERROR_TXT);
  513.  
  514.             IsFatal = FALSE;
  515.  
  516.             break;
  517.  
  518.         case SerErr_BufOverflow:
  519.  
  520.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_READ_BUFFER_OVERFLOWED_TXT);
  521.  
  522.             IsFatal = FALSE;
  523.  
  524.             break;
  525.  
  526.         case SerErr_NoDSR:
  527.  
  528.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_NO_DSR_TXT);
  529.  
  530.             IsFatal = TRUE;
  531.  
  532.             break;
  533.  
  534.         case SerErr_DetectedBreak:
  535.  
  536.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_BREAK_DETECTED_TXT);
  537.  
  538.             IsFatal = TRUE;
  539.  
  540.             break;
  541.  
  542.         default:
  543.  
  544.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_UNKNOWN_CAUSE_TXT);
  545.  
  546.             IsFatal = FALSE;
  547.  
  548.             break;
  549.     }
  550.  
  551.     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_ERROR_TEMPLATE_TXT),Request -> IOSer . io_Error,ErrorMessage);
  552.  
  553.     if(IsFatal)
  554.     {
  555.         TransferError = TRUE;
  556.  
  557.         return(TRUE);
  558.     }
  559.     else
  560.         return(FALSE);
  561. }
  562.  
  563.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  564.      *
  565.      *    Open a file for random access.
  566.      */
  567.  
  568. LONG __saveds __asm
  569. xpr_fopen(register __a0 STRPTR FileName,register __a1 STRPTR AccessMode)
  570. {
  571.     UBYTE         RealName[MAX_FILENAME_LENGTH];
  572.     struct Buffer    *File;
  573.  
  574.     Alerted = CarrierMessage = FALSE;
  575.  
  576.         /* Reset transfer counters. */
  577.  
  578.     ByteVal = ByteMax = TimeVal = TimeMax = LastTimeDif = 0;
  579.  
  580.     LastPercent = -1;
  581.  
  582.         /* Reset CPS statistics. */
  583.  
  584.     CPS_Minimum    = (ULONG)~0;
  585.     CPS_Maximum    = 0;
  586.     CPS_Average    = 0;
  587.     CPS_Current    = 0;
  588.     CPS_Count    = 0;
  589.     CPS_Last    = 0;
  590.  
  591.         /* No window available for output? */
  592.  
  593.     if(!TransferWindow)
  594.         OpenTransferWindow();
  595.  
  596.     if(OriginalName[0])
  597.     {
  598.         if(!Stricmp(ShrunkenName,FileName))
  599.             FileName = OriginalName;
  600.     }
  601.  
  602.         /* Determine the file name. */
  603.  
  604.     FileName = NewFileName(FileName,RealName);
  605.  
  606.         /* Determine file transfer mode... */
  607.  
  608.     if(File = BufferOpen(FileName,AccessMode))
  609.     {
  610.         switch(AccessMode[0])
  611.         {
  612.             case 'r':
  613.  
  614.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  615.                 break;
  616.  
  617.             case 'w':
  618.  
  619.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  620.                 break;
  621.  
  622.             case 'a':
  623.  
  624.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  625.                 break;
  626.         }
  627.  
  628.         CurrentFile = File;
  629.     }
  630.  
  631.     DidTransfer = TRUE;
  632.  
  633.     return((LONG)File);
  634. }
  635.  
  636.     /* xpr_fclose(struct Buffer *File):
  637.      *
  638.      *    Close a file opened by xpr_fopen.
  639.      */
  640.  
  641. LONG __saveds __asm
  642. xpr_fclose(register __a0 struct Buffer *File)
  643. {
  644.     UBYTE            RealName[MAX_FILENAME_LENGTH];
  645.     struct DateStamp    OpenDate;
  646.     BYTE            WriteAccess,
  647.                 Used;
  648.  
  649.         /* Save some information. */
  650.  
  651.     OpenDate    = File -> OpenDate;
  652.     WriteAccess    = File -> WriteAccess;
  653.     Used        = File -> Used;
  654.  
  655.         /* Get the name of the file. */
  656.  
  657.     if(!NameFromFH(File -> FileHandle,RealName,MAX_FILENAME_LENGTH))
  658.         RealName[0] = 0;
  659.  
  660.         /* Close the file and see what it brings... */
  661.  
  662.     if(BufferClose(File) && RealName[0])
  663.     {
  664.             /* Did any access take place at all?
  665.              * xprzmodem.library for example just
  666.              * opens and closes a file in order to
  667.              * see if it exists.
  668.              */
  669.  
  670.         if(!Used)
  671.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  672.         else
  673.         {
  674.                 /* Did we receive or send a file? */
  675.  
  676.             if(WriteAccess)
  677.             {
  678.                 LONG Size;
  679.  
  680.                     /* Did the file remain empty? */
  681.  
  682.                 if(!(Size = GetFileSize(RealName)))
  683.                 {
  684.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  685.  
  686.                         /* Delete empty file. */
  687.  
  688.                     if(DeleteFile(RealName))
  689.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  690.                     else
  691.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  692.                 }
  693.                 else
  694.                 {
  695.                     struct Node *SomeNode;
  696.  
  697.                     if(ByteMax)
  698.                     {
  699.                         if(Size >= ByteMax)
  700.                             AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  701.                         else
  702.                             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  703.                     }
  704.  
  705.                         /* Try to identify the file type. */
  706.  
  707.                     switch(Config -> MiscConfig -> IdentifyFiles)
  708.                     {
  709.                         case IDENTIFY_IGNORE:
  710.  
  711.                             if(Config -> MiscConfig -> CreateIcons)
  712.                                 Identify(RealName,FALSE);
  713.  
  714.                             break;
  715.  
  716.                         case IDENTIFY_FILETYPE:
  717.  
  718.                             Identify(RealName,TRUE);
  719.                             break;
  720.  
  721.                         case IDENTIFY_SOURCE:
  722.  
  723.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  724.  
  725.                             if(Config -> MiscConfig -> CreateIcons)
  726.                                 Identify(RealName,FALSE);
  727.  
  728.                             break;
  729.                     }
  730.  
  731.                     if(CPS_Minimum == (ULONG)~0)
  732.                         CPS_Minimum = 0;
  733.  
  734.                     if(CPS_Count == 0)
  735.                     {
  736.                         CPS_Average    = 0;
  737.                         CPS_Count    = 1;
  738.                     }
  739.  
  740.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  741.  
  742.                     if(SomeNode = CreateGenericListNode(0,RealName))
  743.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  744.                 }
  745.             }
  746.             else
  747.             {
  748.                     /* Set the archived bit on files we uploaded? */
  749.  
  750.                 if(Config -> MiscConfig -> SetArchivedBit)
  751.                 {
  752.                     struct FileInfoBlock *FileInfo;
  753.  
  754.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  755.                     {
  756.                         BPTR FileLock;
  757.  
  758.                             /* Get a lock on it. */
  759.  
  760.                         if(FileLock = Lock(RealName,ACCESS_READ))
  761.                         {
  762.                                 /* Examine the file. */
  763.  
  764.                             if(Examine(FileLock,FileInfo))
  765.                             {
  766.                                     /* Remove the lock. */
  767.  
  768.                                 UnLock(FileLock);
  769.  
  770.                                     /* Set the `archived' bit. */
  771.  
  772.                                 SetProtection(RealName,FileInfo -> fib_Protection | FIBF_ARCHIVE);
  773.                             }
  774.                             else
  775.                                 UnLock(FileLock);
  776.                         }
  777.  
  778.                         FreeDosObject(DOS_FIB,FileInfo);
  779.                     }
  780.                 }
  781.  
  782.                 AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  783.  
  784.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  785.  
  786.                 RemoveUploadListItem(RealName);
  787.             }
  788.         }
  789.     }
  790.  
  791.     CurrentFile = NULL;
  792.  
  793.     return(1);
  794. }
  795.  
  796.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  797.      *
  798.      *    Read a few bytes from a file.
  799.      */
  800.  
  801. LONG __saveds __asm
  802. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  803. {
  804.     return(BufferRead(File,Buffer,Size * Count) / Size);
  805. }
  806.  
  807.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  808.      *
  809.      *    Write a few bytes to a file.
  810.      */
  811.  
  812. LONG __saveds __asm
  813. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  814. {
  815.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  816. }
  817.  
  818.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  819.      *
  820.      *    Move the read/write pointer in a file.
  821.      */
  822.  
  823. LONG __saveds __asm
  824. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  825. {
  826.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  827. }
  828.  
  829.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  830.      *
  831.      *    Read a few bytes from the serial port (including
  832.      *    timeouts).
  833.      */
  834.  
  835. LONG __saveds __asm
  836. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  837. {
  838.         /* No window available for output? */
  839.  
  840.     if(!TransferWindow)
  841.     {
  842.         if(!OpenTransferWindow())
  843.             return(-1);
  844.     }
  845.  
  846.         /* Are both IORequests available? */
  847.  
  848.     if(WriteRequest && ReadRequest)
  849.     {
  850.             /* Valid size parameter? */
  851.  
  852.         if(Size > 0)
  853.         {
  854.                 /* How many bytes are still in the serial buffer? */
  855.  
  856.             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  857.  
  858.             DoIO(WriteRequest);
  859.  
  860.                 /* Return error if carrier is lost. */
  861.  
  862.             if(Config -> SerialConfig -> CheckCarrier)
  863.             {
  864.                 if(WriteRequest -> io_Status & CIAF_COMCD)
  865.                 {
  866.                     if(!CarrierMessage)
  867.                     {
  868.                         CarrierMessage = TRUE;
  869.  
  870.                         AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  871.                     }
  872.  
  873.                     Online = FALSE;
  874.  
  875.                     TransferError = TRUE;
  876.  
  877.                     return(-1);
  878.                 }
  879.             }
  880.  
  881.             /* ALWAYS */
  882.             {
  883.                 register ULONG Waiting;
  884.  
  885.                 if(Waiting = WriteRequest -> IOSer . io_Actual)
  886.                 {
  887.                         /* No timeout specified? Read as many
  888.                          * bytes as available.
  889.                          */
  890.  
  891.                     if(!Timeout)
  892.                     {
  893.                         if(Waiting > Size)
  894.                             Waiting = Size;
  895.  
  896.                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  897.                         ReadRequest -> IOSer . io_Data        = Buffer;
  898.                         ReadRequest -> IOSer . io_Length    = Waiting;
  899.  
  900.                         if(DoIO(ReadRequest))
  901.                         {
  902.                             if(SerialErrorReport(ReadRequest))
  903.                                 return(-1);
  904.                             else
  905.                                 Waiting = ReadRequest -> IOSer . io_Actual;
  906.                         }
  907.  
  908.                         BytesIn += Waiting;
  909.  
  910.                         return((LONG)Waiting);
  911.                     }
  912.  
  913.                         /* Enough data pending to be read? */
  914.  
  915.                     if(Waiting >= Size)
  916.                     {
  917.                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  918.                         ReadRequest -> IOSer . io_Data        = Buffer;
  919.                         ReadRequest -> IOSer . io_Length    = Size;
  920.  
  921.                         if(DoIO(ReadRequest))
  922.                         {
  923.                             if(SerialErrorReport(ReadRequest))
  924.                                 return(-1);
  925.                             else
  926.                                 Size = ReadRequest -> IOSer . io_Actual;
  927.                         }
  928.  
  929.                         BytesIn += Size;
  930.  
  931.                         return(Size);
  932.                     }
  933.                 }
  934.                 else
  935.                 {
  936.                         /* No timeout & no bytes available:
  937.                          * return immediately.
  938.                          */
  939.  
  940.                     if(!Timeout)
  941.                         return(0);
  942.                 }
  943.             }
  944.  
  945.             /* ALWAYS */
  946.             {
  947.                 register ULONG    SignalSet,
  948.                         SerialMask = PORTMASK(ReadPort),
  949.                         WindowMask = PORTMASK(TransferWindow -> UserPort);
  950.  
  951.                     /* Set up the timer. */
  952.  
  953.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  954.                 TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  955.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  956.  
  957.                     /* Set up the read request. */
  958.  
  959.                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  960.                 ReadRequest -> IOSer . io_Data        = Buffer;
  961.                 ReadRequest -> IOSer . io_Length    = Size;
  962.  
  963.                     /* Prevent early termination. */
  964.  
  965.                 ClrSignal(SerialMask | SIG_TIMER);
  966.  
  967.                     /* Start IO... */
  968.  
  969.                 SendIO(ReadRequest);
  970.                 SendIO(TimeRequest);
  971.  
  972.                 FOREVER
  973.                 {
  974.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  975.  
  976.                         /* Abort file transfer? */
  977.  
  978.                     if(SignalSet & WindowMask)
  979.                     {
  980.                         if(CheckAbort(FALSE) == -1)
  981.                         {
  982.                             if(!CheckIO(ReadRequest))
  983.                                 AbortIO(ReadRequest);
  984.  
  985.                             if(!CheckIO(TimeRequest))
  986.                                 AbortIO(TimeRequest);
  987.  
  988.                             WaitIO(ReadRequest);
  989.                             WaitIO(TimeRequest);
  990.  
  991.                             SendAbort = TRUE;
  992.  
  993.                             return(-1);
  994.                         }
  995.                     }
  996.  
  997.                         /* Receive buffer filled? */
  998.  
  999.                     if(SignalSet & SerialMask)
  1000.                     {
  1001.                             /* Abort the timer request. */
  1002.  
  1003.                         if(!CheckIO(TimeRequest))
  1004.                             AbortIO(TimeRequest);
  1005.  
  1006.                         WaitIO(TimeRequest);
  1007.  
  1008.                             /* Did the request terminate gracefully? */
  1009.  
  1010.                         if(WaitIO(ReadRequest))
  1011.                         {
  1012.                             if(SerialErrorReport(ReadRequest))
  1013.                                 return(-1);
  1014.                             else
  1015.                                 Size = ReadRequest -> IOSer . io_Actual;
  1016.                         }
  1017.  
  1018.                         BytesIn += Size;
  1019.  
  1020.                         return(Size);
  1021.                     }
  1022.  
  1023.                         /* Hit by timeout? */
  1024.  
  1025.                     if(SignalSet & SIG_TIMER)
  1026.                     {
  1027.                             /* Abort the read request. */
  1028.  
  1029.                         if(!CheckIO(ReadRequest))
  1030.                             AbortIO(ReadRequest);
  1031.  
  1032.                         WaitIO(ReadRequest);
  1033.  
  1034.                             /* Remove the timer request. */
  1035.  
  1036.                         WaitIO(TimeRequest);
  1037.  
  1038.                             /* Did the driver receive any
  1039.                              * data?
  1040.                              */
  1041.  
  1042.                         if(ReadRequest -> IOSer . io_Actual)
  1043.                         {
  1044.                             BytesIn += ReadRequest -> IOSer . io_Actual;
  1045.  
  1046.                             return((LONG)ReadRequest -> IOSer . io_Actual);
  1047.                         }
  1048.                         else
  1049.                         {
  1050.                                 /* Take a second look and query the number of
  1051.                                  * bytes ready to be received, there may
  1052.                                  * still be some bytes in the buffer.
  1053.                                  * Note: this depends on the way the
  1054.                                  * driver handles read abort.
  1055.                                  */
  1056.  
  1057.                             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1058.  
  1059.                             DoIO(WriteRequest);
  1060.  
  1061.                                 /* Don't read too much. */
  1062.  
  1063.                             if(Size > WriteRequest -> IOSer . io_Actual)
  1064.                                 Size = WriteRequest -> IOSer . io_Actual;
  1065.  
  1066.                                 /* Are there any bytes to be transferred? */
  1067.  
  1068.                             if(Size)
  1069.                             {
  1070.                                     /* Read the data. */
  1071.  
  1072.                                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  1073.                                 ReadRequest -> IOSer . io_Data        = Buffer;
  1074.                                 ReadRequest -> IOSer . io_Length    = Size;
  1075.  
  1076.                                     /* Read the data. */
  1077.  
  1078.                                 if(DoIO(ReadRequest))
  1079.                                 {
  1080.                                     if(SerialErrorReport(ReadRequest))
  1081.                                         return(-1);
  1082.                                     else
  1083.                                         Size = ReadRequest -> IOSer . io_Actual;
  1084.                                 }
  1085.  
  1086.                                 BytesIn += Size;
  1087.                             }
  1088.  
  1089.                             return(Size);
  1090.                         }
  1091.                     }
  1092.                 }
  1093.             }
  1094.         }
  1095.         else
  1096.             return(0);
  1097.     }
  1098.     else
  1099.         return(-1);
  1100. }
  1101.  
  1102.     /* xpr_swrite(APTR Buffer,LONG Size):
  1103.      *
  1104.      *    Write a few bytes to the serial port.
  1105.      */
  1106.  
  1107. LONG __saveds __asm
  1108. xpr_swrite(register __a0 APTR Buffer,register __d0 LONG Size)
  1109. {
  1110.  
  1111.     if(WriteRequest)
  1112.     {
  1113.             /* Return error if carrier is lost. */
  1114.  
  1115.         if(Config -> SerialConfig -> CheckCarrier)
  1116.         {
  1117.                 /* Query the serial status bits. */
  1118.  
  1119.             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1120.  
  1121.             DoIO(WriteRequest);
  1122.  
  1123.                 /* Is the carrier signal still present? */
  1124.  
  1125.             if(WriteRequest -> io_Status & CIAF_COMCD)
  1126.             {
  1127.                 if(!CarrierMessage)
  1128.                 {
  1129.                     CarrierMessage = TRUE;
  1130.  
  1131.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1132.                 }
  1133.  
  1134.                 Online = FALSE;
  1135.  
  1136.                 TransferError = TRUE;
  1137.  
  1138.                 return(-1);
  1139.             }
  1140.         }
  1141.  
  1142.             /* Send the data. */
  1143.  
  1144.         WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  1145.         WriteRequest -> IOSer . io_Data        = Buffer;
  1146.         WriteRequest -> IOSer . io_Length    = Size;
  1147.  
  1148.         if(DoIO(WriteRequest))
  1149.         {
  1150.             if(SerialErrorReport(WriteRequest))
  1151.                 return(-1);
  1152.         }
  1153.         else
  1154.             BytesOut += Size;
  1155.  
  1156.         return(0);
  1157.     }
  1158.     else
  1159.         return(-1);
  1160. }
  1161.  
  1162.     /* xpr_sflush():
  1163.      *
  1164.      *    Release the contents of all serial buffers.
  1165.      */
  1166.  
  1167. LONG __saveds __asm
  1168. xpr_sflush()
  1169. {
  1170.     if(WriteRequest)
  1171.     {
  1172.         WriteRequest -> IOSer . io_Command = CMD_CLEAR;
  1173.  
  1174.         if(DoIO(WriteRequest))
  1175.         {
  1176.             if(SerialErrorReport(WriteRequest))
  1177.                 return(-1);
  1178.         }
  1179.  
  1180.         return(0);
  1181.     }
  1182.     else
  1183.         return(-1);
  1184. }
  1185.  
  1186.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  1187.      *
  1188.      *    Update the information displayed in the transfer window.
  1189.      */
  1190.  
  1191. LONG __saveds __asm
  1192. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  1193. {
  1194.         /* No window available for output? */
  1195.  
  1196.     if(!TransferWindow)
  1197.     {
  1198.         if(!OpenTransferWindow())
  1199.             return(0);
  1200.     }
  1201.  
  1202.     if(UpdateInfo)
  1203.     {
  1204.         BYTE    NewByte = FALSE,
  1205.             NewTime = FALSE;
  1206.  
  1207.         if(TransferWindow -> Flags & WFLG_ZOOMED)
  1208.         {
  1209.             BOOLEAN Refresh;
  1210.  
  1211.             if(!TransferZoomed)
  1212.             {
  1213.                 ULONG Micros;
  1214.  
  1215.                 CurrentTime(&LastSeconds,&Micros);
  1216.  
  1217.                 Refresh = TRUE;
  1218.  
  1219.                 TransferZoomed = TRUE;
  1220.             }
  1221.             else
  1222.             {
  1223.                 ULONG Seconds,Micros;
  1224.  
  1225.                 CurrentTime(&Seconds,&Micros);
  1226.  
  1227.                 if(Seconds > LastSeconds)
  1228.                 {
  1229.                     LastSeconds = Seconds;
  1230.  
  1231.                     Refresh = TRUE;
  1232.                 }
  1233.             }
  1234.  
  1235.             if(Refresh)
  1236.             {
  1237.                 if(LastPercent > 0)
  1238.                     SPrintf(TransferTitleBuffer,"%s [%s %ld%%]",TransferWindowTitle,TruncateName(RealName),LastPercent);
  1239.                 else
  1240.                     SPrintf(TransferTitleBuffer,"%s [%s]",TransferWindowTitle,TruncateName(RealName));
  1241.  
  1242.                 SetWindowTitles(TransferWindow,TransferTitleBuffer,(STRPTR)-1);
  1243.             }
  1244.         }
  1245.         else
  1246.         {
  1247.             if(TransferZoomed)
  1248.             {
  1249.                 SetWindowTitles(TransferWindow,TransferWindowTitle,(STRPTR)-1);
  1250.  
  1251.                 TransferZoomed = FALSE;
  1252.             }
  1253.         }
  1254.  
  1255.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  1256.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_PROTOCOL,GTTX_Text,UpdateInfo -> xpru_protocol,TAG_DONE);
  1257.  
  1258.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  1259.             AddTransferInfo(FALSE,UpdateInfo -> xpru_msg);
  1260.  
  1261.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  1262.             AddTransferInfo(TRUE,UpdateInfo -> xpru_errormsg);
  1263.  
  1264.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  1265.         {
  1266.             STRPTR FileName = UpdateInfo -> xpru_filename;
  1267.  
  1268.             if(OriginalName[0])
  1269.             {
  1270.                 if(!Stricmp(ShrunkenName,FileName))
  1271.                     FileName = OriginalName;
  1272.             }
  1273.  
  1274.             FileName = NewFileName(FileName,RealName);
  1275.  
  1276.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,0,LABX_Text,TruncateName(FileName),TAG_DONE);
  1277.  
  1278.             if(FileTransferInfo)
  1279.             {
  1280.                 if(FileTransferInfo -> CurrentFile)
  1281.                 {
  1282.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1283.  
  1284.                     if(Node -> Node . mln_Succ)
  1285.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,TruncateName(Node -> Name),TAG_DONE);
  1286.                     else
  1287.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,LocaleString(MSG_GLOBAL_NONE_TXT),TAG_DONE);
  1288.                 }
  1289.  
  1290.                 PrintBox(GAD_TRANSFER_SIZE,2,ConvNumber,FileTransferInfo -> TotalSize);
  1291.  
  1292.                 if(FileTransferInfo -> TotalFiles)
  1293.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,(100 * FileTransferInfo -> DoneFiles) / FileTransferInfo -> TotalFiles);
  1294.                 else
  1295.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,0);
  1296.             }
  1297.         }
  1298.  
  1299.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  1300.         {
  1301.             if(CurrentFile)
  1302.             {
  1303.                 if(CurrentFile -> DirLock)
  1304.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber10,UpdateInfo -> xpru_filesize);
  1305.                 else
  1306.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1307.             }
  1308.             else
  1309.                 PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1310.  
  1311.             if(ByteMax = UpdateInfo -> xpru_filesize)
  1312.                 NewByte = TRUE;
  1313.         }
  1314.  
  1315.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  1316.         {
  1317.             if(CurrentFile)
  1318.             {
  1319.                 if(CurrentFile -> DirLock)
  1320.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber10,ByteVal = UpdateInfo -> xpru_bytes);
  1321.                 else
  1322.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1323.             }
  1324.             else
  1325.                 PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1326.  
  1327.             if(FileTransferInfo)
  1328.             {
  1329.                 ULONG Len = FileTransferInfo -> DoneSize + UpdateInfo -> xpru_bytes;
  1330.  
  1331.                 if(FileTransferInfo -> TotalSize)
  1332.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo -> TotalSize);
  1333.                 else
  1334.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  1335.             }
  1336.  
  1337.             if(ByteMax)
  1338.                 NewByte = TRUE;
  1339.  
  1340.             if(CurrentFile)
  1341.             {
  1342.                 if(CurrentFile -> DirLock && !Uploading)
  1343.                 {
  1344.                     if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1345.                     {
  1346.                         if(ByteMax)
  1347.                         {
  1348.                             register LONG Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  1349.  
  1350.                             if(Space >= 0)
  1351.                             {
  1352.                                 register LONG Blocks = CalculateBlocks(ByteMax,CurrentFile -> InfoData . id_BytesPerBlock);
  1353.  
  1354.                                 if(Space < Blocks)
  1355.                                 {
  1356.                                     if(!Alerted)
  1357.                                     {
  1358.                                         Alerted = TRUE;
  1359.  
  1360.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  1361.                                     }
  1362.  
  1363.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT));
  1364.                                 }
  1365.                                 else
  1366.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,"");
  1367.                             }
  1368.                             else
  1369.                                 PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1370.                         }
  1371.                         else
  1372.                             PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1373.                     }
  1374.                 }
  1375.             }
  1376.         }
  1377.  
  1378.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  1379.             PrintBox(GAD_TRANSFER_SIZE,5,ConvNumber,UpdateInfo -> xpru_blocks);
  1380.  
  1381.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate > 0)
  1382.         {
  1383.             register LONG Change;
  1384.  
  1385.             CPS_Current = UpdateInfo -> xpru_datarate;
  1386.  
  1387.             if(CPS_Last)
  1388.             {
  1389.                 if(CPS_Last < UpdateInfo -> xpru_datarate)
  1390.                     Change = (100 * (UpdateInfo -> xpru_datarate - CPS_Last)) / CPS_Last;
  1391.                 else
  1392.                     Change = (100 * (CPS_Last - UpdateInfo -> xpru_datarate)) / CPS_Last;
  1393.             }
  1394.             else
  1395.                 Change = 100;
  1396.  
  1397.             if(Change > 1)
  1398.             {
  1399.                 PrintBox(GAD_TRANSFER_SECONDS,0,ConvNumber,UpdateInfo -> xpru_datarate);
  1400.  
  1401.                 CPS_Last = UpdateInfo -> xpru_datarate;
  1402.             }
  1403.  
  1404.             if(UpdateInfo -> xpru_datarate < CPS_Minimum)
  1405.                 CPS_Minimum = UpdateInfo -> xpru_datarate;
  1406.  
  1407.             if(UpdateInfo -> xpru_datarate > CPS_Maximum)
  1408.                 CPS_Maximum = UpdateInfo -> xpru_datarate;
  1409.  
  1410.             if((ULONG)(CPS_Average + UpdateInfo -> xpru_datarate) >= CPS_Average)
  1411.             {
  1412.                 CPS_Average += UpdateInfo -> xpru_datarate;
  1413.  
  1414.                 CPS_Count++;
  1415.             }
  1416.         }
  1417.  
  1418.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  1419.             PrintBox(GAD_TRANSFER_SECONDS,1,ConvNumber,UpdateInfo -> xpru_chardelay);
  1420.  
  1421.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  1422.             PrintBox(GAD_TRANSFER_SECONDS,2,ConvNumber,UpdateInfo -> xpru_packetdelay);
  1423.  
  1424.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  1425.         {
  1426.             if(UpdateInfo -> xpru_packettype > 32 && UpdateInfo -> xpru_packettype < 256)
  1427.             {
  1428.                 if(IsPrintable[UpdateInfo -> xpru_packettype])
  1429.                     PrintBox(GAD_TRANSFER_SECONDS,3,"`%lc'",UpdateInfo -> xpru_packettype);
  1430.                 else
  1431.                     PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1432.             }
  1433.             else
  1434.                 PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1435.         }
  1436.  
  1437.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  1438.             PrintBox(GAD_TRANSFER_SECONDS,4,UpdateInfo -> xpru_blockcheck);
  1439.  
  1440.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  1441.             PrintBox(GAD_TRANSFER_SECONDS,5,ConvNumber,UpdateInfo -> xpru_blocksize);
  1442.  
  1443.  
  1444.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  1445.         {
  1446.             PrintBox(GAD_TRANSFER_TOTALTIME,0,UpdateInfo -> xpru_expecttime);
  1447.  
  1448.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo -> xpru_expecttime))
  1449.                 NewTime = TRUE;
  1450.         }
  1451.  
  1452.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  1453.         {
  1454.             PrintBox(GAD_TRANSFER_TOTALTIME,1,UpdateInfo -> xpru_elapsedtime);
  1455.  
  1456.             TimeVal = GetSeconds((STRPTR)UpdateInfo -> xpru_elapsedtime);
  1457.  
  1458.             if(TimeMax)
  1459.                 NewTime = TRUE;
  1460.         }
  1461.  
  1462.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  1463.             PrintBox(GAD_TRANSFER_ERRORS,0,ConvNumber,UpdateInfo -> xpru_errors);
  1464.  
  1465.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  1466.             PrintBox(GAD_TRANSFER_ERRORS,1,ConvNumber,UpdateInfo -> xpru_timeouts);
  1467.  
  1468.         if(NewByte)
  1469.         {
  1470.             LONG Percent;
  1471.  
  1472.             if(ByteMax)
  1473.                 Percent = (100 * ByteVal) / ByteMax;
  1474.             else
  1475.                 Percent = 0;
  1476.  
  1477.             if(Percent != LastPercent)
  1478.             {
  1479.                 UBYTE LocalBuffer[10];
  1480.  
  1481.                 SPrintf(LocalBuffer,"%ld%%",Percent);
  1482.  
  1483.                 LastPercent = Percent;
  1484.  
  1485.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_PERCENT,
  1486.                     LAGA_Percent,    Percent,
  1487.                     LAGA_InfoText,    LocalBuffer,
  1488.                 TAG_DONE);
  1489.             }
  1490.         }
  1491.  
  1492.         if(NewTime)
  1493.         {
  1494.             register LONG TimeDif,Change;
  1495.  
  1496.             if(TimeVal > TimeMax)
  1497.                 TimeDif = 0;
  1498.             else
  1499.                 TimeDif = TimeMax - TimeVal;
  1500.  
  1501.             if(LastTimeDif)
  1502.             {
  1503.                 if(LastTimeDif < TimeDif)
  1504.                     Change = (100 * (TimeDif - LastTimeDif)) / LastTimeDif;
  1505.                 else
  1506.                     Change = (100 * (LastTimeDif - TimeDif)) / LastTimeDif;
  1507.             }
  1508.             else
  1509.                 Change = 100;
  1510.  
  1511.                 /* Don't update the display unless the change
  1512.                  * exceeds 2% of the previous value.
  1513.                  */
  1514.  
  1515.             if(Change > 2)
  1516.             {
  1517.                 UBYTE    LocalBuffer[10];
  1518.                 LONG    Percent;
  1519.  
  1520.                 LastTimeDif = TimeDif;
  1521.  
  1522.                 if(TimeMax)
  1523.                     Percent = (100 * TimeDif) / TimeMax;
  1524.                 else
  1525.                     Percent = 0;
  1526.  
  1527.                 SPrintf(LocalBuffer,"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  1528.  
  1529.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_TIME,
  1530.                     LAGA_Percent,    Percent,
  1531.                     LAGA_InfoText,    LocalBuffer,
  1532.                 TAG_DONE);
  1533.  
  1534.                     /* A rapidly changing transfer time display would
  1535.                      * cause the transfer completion time display to
  1536.                      * change at the same pace. As the completion time
  1537.                      * display calculation is rather costly, a change smaller
  1538.                      * than 5% of the previous value is silently ignored.
  1539.                      */
  1540.  
  1541.                 if(Change > 5)
  1542.                 {
  1543.                     UBYTE            DateTimeBuffer[256];
  1544.                     struct DateStamp    Stamp;
  1545.  
  1546.                         /* Obtain current time. */
  1547.  
  1548.                     DateStamp(&Stamp);
  1549.  
  1550.                         /* Add the time to go. */
  1551.  
  1552.                     Stamp . ds_Tick        += (TimeDif % 60) * TICKS_PER_SECOND;
  1553.                     Stamp . ds_Minute    += TimeDif / 60 + Stamp . ds_Tick / (60 * TICKS_PER_SECOND);
  1554.                     Stamp . ds_Days        += Stamp . ds_Minute / 1440;
  1555.  
  1556.                     Stamp . ds_Tick        %= 60 * TICKS_PER_SECOND;
  1557.                     Stamp . ds_Minute    %= 1440;
  1558.  
  1559.                         /* Conversion succeeded? */
  1560.  
  1561.                     if(FormatStamp(&Stamp,NULL,NULL,DateTimeBuffer,TRUE))
  1562.                         PrintBox(GAD_TRANSFER_FILE,3,DateTimeBuffer);
  1563.                 }
  1564.             }
  1565.         }
  1566.     }
  1567.  
  1568.     if(TransferPerfWindow)
  1569.     {
  1570.         struct RastPort *RPort = TransferPerfWindow -> RPort;
  1571.         LONG Height,Left,Top,Min,Avg,Cur;
  1572.  
  1573.         Left = TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1);
  1574.         Height = TransferPerfWindow -> Height - (TransferPerfWindow -> BorderTop + TransferPerfWindow -> BorderBottom + 1);
  1575.         Top = TransferPerfWindow -> BorderTop + Height;
  1576.  
  1577.         if(CPS_Maximum && CPS_Maximum != ~0)
  1578.         {
  1579.             Min = (Height * CPS_Minimum) / CPS_Maximum;
  1580.             Cur = (Height * CPS_Current) / CPS_Maximum;
  1581.  
  1582.             if(CPS_Count)
  1583.                 Avg = ((CPS_Average / CPS_Count) * Height) / CPS_Maximum;
  1584.             else
  1585.                 Avg = 0;
  1586.         }
  1587.         else
  1588.             Min = Avg = Cur = 0;
  1589.  
  1590.         if(CPL_Min == -1)
  1591.             CPL_Min = Min;
  1592.  
  1593.         if(CPL_Avg == -1)
  1594.             CPL_Avg = Avg;
  1595.  
  1596.         if(CPL_Cur == -1)
  1597.             CPL_Cur = Cur;
  1598.  
  1599.         ScrollRaster(RPort,1,0,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  1600.  
  1601.         if(CPL_Cur != -1 && Cur != -1)
  1602.         {
  1603.             SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
  1604.             Move(RPort,Left,Top - CPL_Cur);
  1605.             Draw(RPort,Left,Top - Cur);
  1606.         }
  1607.  
  1608.         if(CPL_Min != -1 && Min != -1)
  1609.         {
  1610.             SetAPen(RPort,DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN]);
  1611.             Move(RPort,Left,Top - CPL_Min);
  1612.             Draw(RPort,Left,Top - Min);
  1613.         }
  1614.  
  1615.         if(CPL_Avg != -1 && Avg != -1)
  1616.         {
  1617.             SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  1618.             Move(RPort,Left,Top - CPL_Avg);
  1619.             Draw(RPort,Left,Top - Avg);
  1620.         }
  1621.  
  1622.         CPL_Min = Min;
  1623.         CPL_Avg = Avg;
  1624.         CPL_Cur = Cur;
  1625.     }
  1626.  
  1627.     return(1);
  1628. }
  1629.  
  1630.     /* xpr_chkabort():
  1631.      *
  1632.      *    Check if the user has aborted the transfer.
  1633.      */
  1634.  
  1635. LONG __saveds __asm
  1636. xpr_chkabort()
  1637. {
  1638.     LONG Result;
  1639.  
  1640.     Result = CheckAbort(Config -> SerialConfig -> CheckCarrier);
  1641.  
  1642.     return(Result);
  1643. }
  1644.  
  1645.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  1646.      *
  1647.      *    Prompt the user for string input.
  1648.      */
  1649.  
  1650. LONG __saveds __asm
  1651. xpr_gets(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  1652. {
  1653.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1654.  
  1655.     struct LayoutHandle    *Handle;
  1656.     LONG             Success = FALSE;
  1657.     UBYTE             LocalBuffer[256];
  1658.  
  1659.     if(strlen(Buffer) > 255)
  1660.     {
  1661.         CopyMem(Buffer,LocalBuffer,255);
  1662.  
  1663.         LocalBuffer[255] = 0;
  1664.     }
  1665.     else
  1666.         strcpy(LocalBuffer,Buffer);
  1667.  
  1668.     if(!Prompt)
  1669.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1670.  
  1671.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1672.         LH_LocaleHook,    &LocaleHook,
  1673.     TAG_DONE))
  1674.     {
  1675.         struct Window *Window;
  1676.  
  1677.         LT_New(Handle,
  1678.             LA_Type,    VERTICAL_KIND,
  1679.         TAG_DONE);
  1680.         {
  1681.             LT_New(Handle,
  1682.                 LA_Type,    VERTICAL_KIND,
  1683.                 LA_LabelText,    Prompt,
  1684.             TAG_DONE);
  1685.             {
  1686.                 LT_New(Handle,
  1687.                     LA_Type,    STRING_KIND,
  1688.                     LA_STRPTR,    LocalBuffer,
  1689.                     LA_ID,        GAD_STRING,
  1690.                     LA_Chars,    60,
  1691.                 TAG_DONE);
  1692.  
  1693.                 LT_EndGroup(Handle);
  1694.             }
  1695.  
  1696.             LT_New(Handle,
  1697.                 LA_Type,VERTICAL_KIND,
  1698.             TAG_DONE);
  1699.             {
  1700.                 LT_New(Handle,
  1701.                     LA_Type,    XBAR_KIND,
  1702.                     LAXB_FullSize,    TRUE,
  1703.                 TAG_DONE);
  1704.  
  1705.                 LT_EndGroup(Handle);
  1706.             }
  1707.  
  1708.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1709.                 LAGR_SameSize,    TRUE,
  1710.                 LAGR_Spread,    TRUE,
  1711.             TAG_DONE);
  1712.             {
  1713.                 LT_New(Handle,
  1714.                     LA_Type,    BUTTON_KIND,
  1715.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1716.                     LA_ID,        GAD_OK,
  1717.                     LABT_ReturnKey,    TRUE,
  1718.                     LABT_ExtraFat,    TRUE,
  1719.                 TAG_DONE);
  1720.  
  1721.                 LT_New(Handle,
  1722.                     LA_Type,    BUTTON_KIND,
  1723.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1724.                     LA_ID,        GAD_CANCEL,
  1725.                     LABT_EscKey,    TRUE,
  1726.                     LABT_ExtraFat,    TRUE,
  1727.                 TAG_DONE);
  1728.  
  1729.                 LT_EndGroup(Handle);
  1730.             }
  1731.         }
  1732.  
  1733.         if(Window = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1734.             LAWN_HelpHook,        &GuideHook,
  1735.             WA_DepthGadget,        TRUE,
  1736.             WA_CloseGadget,        TRUE,
  1737.             WA_DragBar,        TRUE,
  1738.             WA_RMBTrap,        TRUE,
  1739.             WA_Activate,        TRUE,
  1740.         TAG_DONE))
  1741.         {
  1742.             struct IntuiMessage    *Message;
  1743.             BOOLEAN             Done = FALSE;
  1744.             ULONG             MsgClass,
  1745.                          MsgQualifier;
  1746.             UWORD             MsgCode;
  1747.             struct Gadget        *MsgGadget;
  1748.  
  1749.             PushWindow(Window);
  1750.  
  1751.             LT_ShowWindow(Handle,TRUE);
  1752.  
  1753.             LT_Activate(Handle,GAD_STRING);
  1754.  
  1755.             do
  1756.             {
  1757.                 if(Wait(PORTMASK(Window -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1758.                     break;
  1759.  
  1760.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  1761.                 {
  1762.                     MsgClass    = Message -> Class;
  1763.                     MsgQualifier    = Message -> Qualifier;
  1764.                     MsgCode        = Message -> Code;
  1765.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1766.  
  1767.                     GT_ReplyIMsg(Message);
  1768.  
  1769.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1770.  
  1771.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1772.                         Done = TRUE;
  1773.  
  1774.                     if(MsgClass == IDCMP_GADGETUP)
  1775.                     {
  1776.                         switch(MsgGadget -> GadgetID)
  1777.                         {
  1778.                             case GAD_STRING:
  1779.  
  1780.                                 if(MsgCode == '\r')
  1781.                                 {
  1782.                                     if(strcmp(Buffer,LocalBuffer))
  1783.                                         NewOptions = TRUE;
  1784.  
  1785.                                     strcpy(Buffer,LocalBuffer);
  1786.  
  1787.                                     Success = Done = TRUE;
  1788.  
  1789.                                     LT_PressButton(Handle,GAD_OK);
  1790.                                 }
  1791.  
  1792.                                 break;
  1793.  
  1794.                             case GAD_OK:
  1795.  
  1796.                                 if(strcmp(Buffer,LocalBuffer))
  1797.                                     NewOptions = TRUE;
  1798.  
  1799.                                 strcpy(Buffer,LocalBuffer);
  1800.  
  1801.                                 Success = Done = TRUE;
  1802.  
  1803.                                 break;
  1804.  
  1805.                             case GAD_CANCEL:
  1806.  
  1807.                                 Done = TRUE;
  1808.                                 break;
  1809.                         }
  1810.                     }
  1811.                 }
  1812.             }
  1813.             while(!Done);
  1814.  
  1815.             PopWindow();
  1816.         }
  1817.  
  1818.         LT_DeleteHandle(Handle);
  1819.     }
  1820.  
  1821.     return(Success);
  1822. }
  1823.  
  1824.     /* xpr_setserial(LONG Status):
  1825.      *
  1826.      *    Set/read the serial status (parameters).
  1827.      */
  1828.  
  1829. LONG __saveds __asm
  1830. xpr_setserial(register __d0 LONG Status)
  1831. {
  1832.     if(WriteRequest)
  1833.     {
  1834.         STATIC LONG XprBauds[12] =
  1835.         {
  1836.                110,
  1837.                300,
  1838.               1200,
  1839.               2400,
  1840.               4800,
  1841.               9600,
  1842.              19200,
  1843.              31250,
  1844.              38400,
  1845.              57600,
  1846.              76800,
  1847.             115200
  1848.         };
  1849.  
  1850.         LONG Return,i;
  1851.  
  1852.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1853.  
  1854.         DoIO(WriteRequest);
  1855.  
  1856.         Return = WriteRequest -> io_SerFlags & 0xFF;
  1857.  
  1858.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  1859.             Return |= ST_PARTYMARKON;
  1860.  
  1861.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  1862.             Return |= ST_PARTYMARK;
  1863.  
  1864.         if(WriteRequest -> io_StopBits == 2)
  1865.             Return |= ST_2BITS;
  1866.  
  1867.         if(WriteRequest -> io_ReadLen == 7)
  1868.             Return |= ST_READ7;
  1869.  
  1870.         if(WriteRequest -> io_WriteLen == 7)
  1871.             Return |= ST_WRITE7;
  1872.  
  1873.         for(i = 0 ; i < 12 ; i++)
  1874.         {
  1875.             if(XprBauds[i] >= WriteRequest -> io_Baud)
  1876.             {
  1877.                 Return |= (i << 16);
  1878.  
  1879.                 break;
  1880.             }
  1881.         }
  1882.  
  1883.             /* Update serial parameters, don't change
  1884.              * the baud rate however.
  1885.              */
  1886.  
  1887.         if(Status != -1)
  1888.         {
  1889.             WriteRequest -> io_SerFlags = Status & 0xFF;
  1890.             WriteRequest -> io_ExtFlags = 0;
  1891.  
  1892.             if(Status & ST_PARTYMARKON)
  1893.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  1894.  
  1895.             if(Status & ST_PARTYMARK)
  1896.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  1897.  
  1898.             if(Status & ST_2BITS)
  1899.                 WriteRequest -> io_StopBits = 2;
  1900.             else
  1901.                 WriteRequest -> io_StopBits = 1;
  1902.  
  1903.             if(Status & ST_READ7)
  1904.                 WriteRequest -> io_ReadLen = 7;
  1905.             else
  1906.                 WriteRequest -> io_ReadLen = 8;
  1907.  
  1908.             if(Status & ST_WRITE7)
  1909.                 WriteRequest -> io_WriteLen = 7;
  1910.             else
  1911.                 WriteRequest -> io_WriteLen = 8;
  1912.  
  1913.             ReadRequest -> io_Baud        = WriteRequest -> io_Baud;
  1914.             ReadRequest -> io_SerFlags    = WriteRequest -> io_SerFlags;
  1915.             ReadRequest -> io_ExtFlags    = WriteRequest -> io_ExtFlags;
  1916.             ReadRequest -> io_StopBits    = WriteRequest -> io_StopBits;
  1917.             ReadRequest -> io_ReadLen    = WriteRequest -> io_ReadLen;
  1918.             ReadRequest -> io_WriteLen    = WriteRequest -> io_WriteLen;
  1919.  
  1920.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1921.  
  1922.             DoIO(WriteRequest);
  1923.  
  1924.             ReadRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1925.  
  1926.             DoIO(ReadRequest);
  1927.  
  1928.             GetFlags(Config,WriteRequest);
  1929.         }
  1930.  
  1931.         return(Return);
  1932.     }
  1933.     else
  1934.         return(-1);
  1935. }
  1936.  
  1937.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  1938.      *
  1939.      *    Batch file upload: find the first matching file and return
  1940.      *    its name.
  1941.      */
  1942.  
  1943. LONG __saveds __asm
  1944. xpr_ffirst(register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1945. {
  1946.     if(FileTransferInfo)
  1947.     {
  1948.         FileTransferInfo -> DoneSize    = 0;
  1949.         FileTransferInfo -> DoneFiles    = 0;
  1950.  
  1951.         FileTransferInfo -> CurrentFile    = (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
  1952.         FileTransferInfo -> CurrentSize    = FileTransferInfo -> CurrentFile -> Size;
  1953.  
  1954.         if(Config -> TransferConfig -> MangleFileNames)
  1955.         {
  1956.             UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  1957.  
  1958.             strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  1959.  
  1960.             ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  1961.  
  1962.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1963.  
  1964.             Char = PathPart(Buffer);
  1965.  
  1966.             *Char = 0;
  1967.  
  1968.             AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  1969.  
  1970.             strcpy(ShrunkenName,Buffer);
  1971.         }
  1972.         else
  1973.         {
  1974.             OriginalName[0] = 0;
  1975.  
  1976.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1977.         }
  1978.  
  1979.         return(1);
  1980.     }
  1981.     else
  1982.         return(0);
  1983. }
  1984.  
  1985.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  1986.      *
  1987.      *    Batch file upload: find the next matching file
  1988.      *    - if any - and return its name.
  1989.      */
  1990.  
  1991. LONG __saveds __asm
  1992. xpr_fnext(register __d0 LONG OldState,register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1993. {
  1994.     if(FileTransferInfo)
  1995.     {
  1996.         if(FileTransferInfo -> CurrentFile -> Node . mln_Succ -> mln_Succ)
  1997.         {
  1998.             FileTransferInfo -> DoneSize    += FileTransferInfo -> CurrentSize;
  1999.             FileTransferInfo -> DoneFiles    += 1;
  2000.  
  2001.             FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  2002.             FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
  2003.  
  2004.             if(Config -> TransferConfig -> MangleFileNames)
  2005.             {
  2006.                 UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2007.  
  2008.                 strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  2009.  
  2010.                 ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  2011.  
  2012.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2013.  
  2014.                 Char = PathPart(Buffer);
  2015.  
  2016.                 *Char = 0;
  2017.  
  2018.                 AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2019.  
  2020.                 strcpy(ShrunkenName,Buffer);
  2021.             }
  2022.             else
  2023.             {
  2024.                 OriginalName[0] = 0;
  2025.  
  2026.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2027.             }
  2028.  
  2029.             return(1);
  2030.         }
  2031.     }
  2032.  
  2033.     return(0);
  2034. }
  2035.  
  2036.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  2037.      *
  2038.      *    Return information on a given file.
  2039.      */
  2040.  
  2041. LONG __saveds __asm
  2042. xpr_finfo(register __a0 STRPTR FileName,register __d0 LONG InfoType)
  2043. {
  2044.     struct FileInfoBlock    *FileInfo;
  2045.     LONG             Size;
  2046.  
  2047.     switch(InfoType)
  2048.     {
  2049.             /* Return the file size. */
  2050.  
  2051.         case 1:    Size = 0;
  2052.  
  2053.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2054.             {
  2055.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  2056.                 BPTR    FileLock;
  2057.  
  2058.                 if(OriginalName[0])
  2059.                 {
  2060.                     if(!Stricmp(ShrunkenName,FileName))
  2061.                         FileName = NewFileName(OriginalName,RealName);
  2062.                     else
  2063.                         FileName = NewFileName(FileName,RealName);
  2064.                 }
  2065.                 else
  2066.                     FileName = NewFileName(FileName,RealName);
  2067.  
  2068.                 if(FileLock = Lock(FileName,ACCESS_READ))
  2069.                 {
  2070.                     if(Examine(FileLock,FileInfo))
  2071.                     {
  2072.                         if(FileInfo -> fib_DirEntryType < 0)
  2073.                             Size = FileInfo -> fib_Size;
  2074.                     }
  2075.  
  2076.                     UnLock(FileLock);
  2077.                 }
  2078.  
  2079.                 FreeDosObject(DOS_FIB,FileInfo);
  2080.             }
  2081.  
  2082.             return(Size);
  2083.  
  2084.             /* Return the file transfer mode. */
  2085.  
  2086.         case 2:    return(BinaryTransfer ? 1 : 2);
  2087.  
  2088.             /* Ignore the rest. */
  2089.  
  2090.         default:return(0);
  2091.     }
  2092. }
  2093.  
  2094.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  2095.      *
  2096.      *    Provide a more polished user interface to set the
  2097.      *    transfer protocol options.
  2098.      */
  2099.  
  2100. ULONG __saveds __asm
  2101. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  2102. {
  2103.     if(NumOpts && Opts)
  2104.     {
  2105.         enum    {    GAD_USE=1,GAD_CANCEL,GAD_SPECIAL };
  2106.  
  2107.         struct LayoutHandle    *Handle;
  2108.         ULONG             Flags = NULL;
  2109.  
  2110.             /* We only have 32 bits! */
  2111.  
  2112.         if(NumOpts > 32)
  2113.             NumOpts = 32;
  2114.  
  2115.         if(Handle = LT_CreateHandleTags(Window -> WScreen,
  2116.             LH_LocaleHook,    &LocaleHook,
  2117.         TAG_DONE))
  2118.         {
  2119.             struct Window    *Window;
  2120.             LONG         i,Split;
  2121.  
  2122.             if(NumOpts > 16)
  2123.                 Split = NumOpts / 2;
  2124.             else
  2125.                 Split = -1;
  2126.  
  2127.             LT_New(Handle,
  2128.                 LA_Type,    VERTICAL_KIND,
  2129.             TAG_DONE);
  2130.             {
  2131.                 LT_New(Handle,
  2132.                     LA_Type,    HORIZONTAL_KIND,
  2133.                     LA_LabelID,    MSG_V36_1501,
  2134.                 TAG_DONE);
  2135.                 {
  2136.                     LT_New(Handle,
  2137.                         LA_Type,    VERTICAL_KIND,
  2138.                     TAG_DONE);
  2139.                     {
  2140.                         for(i = 0 ; i < NumOpts ; i++)
  2141.                         {
  2142.                             if(Opts[i])
  2143.                             {
  2144.                                 switch(Opts[i] -> xpro_type)
  2145.                                 {
  2146.                                     case XPRO_BOOLEAN:
  2147.  
  2148.                                         LT_New(Handle,
  2149.                                             LA_Type,    CHECKBOX_KIND,
  2150.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2151.                                             LA_ID,        GAD_SPECIAL + i,
  2152.                                             GTCB_Checked,    GetOptionMode(Opts[i]),
  2153.                                         TAG_DONE);
  2154.  
  2155.                                         break;
  2156.  
  2157.                                     case XPRO_LONG:
  2158.  
  2159.                                         LT_New(Handle,
  2160.                                             LA_Type,        INTEGER_KIND,
  2161.                                             LA_LabelText,        Opts[i] -> xpro_description,
  2162.                                             LA_ID,            GAD_SPECIAL + i,
  2163.                                             LA_Chars,        20,
  2164.                                             GTIN_Number,        Atol(Opts[i] -> xpro_value),
  2165.                                             LAIN_UseIncrementers,    TRUE,
  2166.                                         TAG_DONE);
  2167.  
  2168.                                         break;
  2169.  
  2170.                                     case XPRO_STRING:
  2171.  
  2172.                                         LT_New(Handle,
  2173.                                             LA_Type,    STRING_KIND,
  2174.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2175.                                             LA_ID,        GAD_SPECIAL + i,
  2176.                                             LA_Chars,    20,
  2177.                                             GTST_String,    Opts[i] -> xpro_value,
  2178.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2179.                                         TAG_DONE);
  2180.  
  2181.                                         break;
  2182.  
  2183.                                     case XPRO_COMMPAR:
  2184.  
  2185.                                         LT_New(Handle,
  2186.                                             LA_Type,    STRING_KIND,
  2187.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2188.                                             LA_ID,        GAD_SPECIAL + i,
  2189.                                             LA_Chars,    20,
  2190.                                             LA_HighLabel,    TRUE,
  2191.                                             GTST_String,    Opts[i] -> xpro_value,
  2192.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2193.                                         TAG_DONE);
  2194.  
  2195.                                         break;
  2196.  
  2197.                                     case XPRO_HEADER:
  2198.  
  2199.                                         LT_New(Handle,
  2200.                                             LA_Type,    TEXT_KIND,
  2201.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2202.                                             LA_HighLabel,    TRUE,
  2203.                                             GTTX_Text,    " ",
  2204.                                         TAG_DONE);
  2205.  
  2206.                                         break;
  2207.  
  2208.                                     case XPRO_COMMAND:
  2209.  
  2210.                                         LT_New(Handle,
  2211.                                             LA_Type,    BUTTON_KIND,
  2212.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2213.                                             LA_ID,        GAD_SPECIAL + i,
  2214.                                             LA_Chars,    20,
  2215.                                         TAG_DONE);
  2216.  
  2217.                                         break;
  2218.                                 }
  2219.                             }
  2220.  
  2221.                             if(i == Split)
  2222.                             {
  2223.                                 LT_EndGroup(Handle);
  2224.  
  2225.                                 LT_New(Handle,
  2226.                                     LA_Type,    VERTICAL_KIND,
  2227.                                 TAG_DONE);
  2228.                             }
  2229.                         }
  2230.  
  2231.                         LT_EndGroup(Handle);
  2232.                     }
  2233.  
  2234.                     LT_EndGroup(Handle);
  2235.                 }
  2236.  
  2237.                 LT_New(Handle,
  2238.                     LA_Type,VERTICAL_KIND,
  2239.                 TAG_DONE);
  2240.                 {
  2241.                     LT_New(Handle,
  2242.                         LA_Type,    XBAR_KIND,
  2243.                         LAXB_FullSize,    TRUE,
  2244.                     TAG_DONE);
  2245.     
  2246.                     LT_EndGroup(Handle);
  2247.                 }
  2248.  
  2249.                 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  2250.                     LAGR_SameSize,    TRUE,
  2251.                     LAGR_Spread,    TRUE,
  2252.                 TAG_DONE);
  2253.                 {
  2254.                     LT_New(Handle,
  2255.                         LA_Type,    BUTTON_KIND,
  2256.                         LA_LabelID,    MSG_GLOBAL_USE_GAD,
  2257.                         LA_ID,        GAD_USE,
  2258.                         LABT_ReturnKey,    TRUE,
  2259.                         LABT_ExtraFat,    TRUE,
  2260.                     TAG_DONE);
  2261.  
  2262.                     LT_New(Handle,
  2263.                         LA_Type,    BUTTON_KIND,
  2264.                         LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  2265.                         LA_ID,        GAD_CANCEL,
  2266.                         LABT_EscKey,    TRUE,
  2267.                         LABT_ExtraFat,    TRUE,
  2268.                     TAG_DONE);
  2269.  
  2270.                     LT_EndGroup(Handle);
  2271.                 }
  2272.  
  2273.                 LT_EndGroup(Handle);
  2274.             }
  2275.  
  2276.             if(Window = LT_Layout(Handle,OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  2277.                 LAWN_HelpHook,        &GuideHook,
  2278.                 WA_DepthGadget,        TRUE,
  2279.                 WA_CloseGadget,        TRUE,
  2280.                 WA_DragBar,        TRUE,
  2281.                 WA_RMBTrap,        TRUE,
  2282.                 WA_Activate,        TRUE,
  2283.             TAG_DONE))
  2284.             {
  2285.                 struct IntuiMessage    *Message;
  2286.                 BOOLEAN             Done = FALSE;
  2287.                 ULONG             MsgClass,
  2288.                              MsgQualifier;
  2289.                 UWORD             MsgCode;
  2290.                 struct Gadget        *MsgGadget;
  2291.                 BOOLEAN             CheckFlags = FALSE;
  2292.  
  2293.                 PushWindow(Window);
  2294.  
  2295.                 LT_ShowWindow(Handle,TRUE);
  2296.  
  2297.                 do
  2298.                 {
  2299.                     if(Wait(PORTMASK(Window -> UserPort) | SIG_BREAK) & SIG_BREAK)
  2300.                         break;
  2301.  
  2302.                     while(Message = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  2303.                     {
  2304.                         MsgClass    = Message -> Class;
  2305.                         MsgQualifier    = Message -> Qualifier;
  2306.                         MsgCode        = Message -> Code;
  2307.                         MsgGadget    = (struct Gadget *)Message -> IAddress;
  2308.  
  2309.                         GT_ReplyIMsg(Message);
  2310.  
  2311.                         LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  2312.  
  2313.                         if(MsgClass == IDCMP_CLOSEWINDOW)
  2314.                             Done = TRUE;
  2315.  
  2316.                         if(MsgClass == IDCMP_GADGETUP)
  2317.                         {
  2318.                             switch(MsgGadget -> GadgetID)
  2319.                             {
  2320.                                 case GAD_USE:
  2321.  
  2322.                                     Done = CheckFlags = TRUE;
  2323.                                     break;
  2324.  
  2325.                                 case GAD_CANCEL:
  2326.  
  2327.                                     Done = TRUE;
  2328.                                     break;
  2329.  
  2330.                                 default:
  2331.  
  2332.                                     if(MsgGadget -> GadgetID - GAD_SPECIAL < NumOpts)
  2333.                                     {
  2334.                                         i = MsgGadget -> GadgetID - GAD_SPECIAL;
  2335.  
  2336.                                         if(Opts[i] -> xpro_type == XPRO_COMMAND || (Opts[i] -> xpro_type == XPRO_COMMPAR && MsgCode != '\t'))
  2337.                                         {
  2338.                                             Flags = (1L << i);
  2339.  
  2340.                                             XPRCommandSelected = Done = CheckFlags = TRUE;
  2341.                                         }
  2342.                                     }
  2343.  
  2344.                                     break;
  2345.                             }
  2346.                         }
  2347.                     }
  2348.                 }
  2349.                 while(!Done);
  2350.  
  2351.                 PopWindow();
  2352.  
  2353.                 if(CheckFlags)
  2354.                 {
  2355.                     LT_LockWindow(Window);
  2356.  
  2357.                     for(i = 0 ; i < NumOpts ; i++)
  2358.                     {
  2359.                         if(Opts[i])
  2360.                         {
  2361.                             switch(Opts[i] -> xpro_type)
  2362.                             {
  2363.                                 case XPRO_BOOLEAN:
  2364.  
  2365.                                     if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE) != GetOptionMode(Opts[i]))
  2366.                                     {
  2367.                                         Flags |= (1L << i);
  2368.  
  2369.                                         if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2370.                                             strcpy(Opts[i] -> xpro_value,"yes");
  2371.                                         else
  2372.                                             strcpy(Opts[i] -> xpro_value,"no");
  2373.  
  2374.                                         NewOptions = TRUE;
  2375.                                     }
  2376.  
  2377.                                     break;
  2378.  
  2379.                                 case XPRO_LONG:
  2380.  
  2381.                                     if(Atol(Opts[i] -> xpro_value) != LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2382.                                     {
  2383.                                         Flags |= (1L << i);
  2384.  
  2385.                                         SPrintf(Opts[i] -> xpro_value,"%ld",LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2386.  
  2387.                                         NewOptions = TRUE;
  2388.                                     }
  2389.  
  2390.                                     break;
  2391.  
  2392.                                 case XPRO_STRING:
  2393.  
  2394.                                     if(strcmp(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE)))
  2395.                                     {
  2396.                                         Flags |= (1L << i);
  2397.  
  2398.                                         strcpy(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2399.  
  2400.                                         NewOptions = TRUE;
  2401.                                     }
  2402.  
  2403.                                     break;
  2404.                             }
  2405.                         }
  2406.                     }
  2407.  
  2408.                     LT_UnlockWindow(Window);
  2409.                 }
  2410.                 else
  2411.                     Flags = NULL;
  2412.             }
  2413.  
  2414.             LT_DeleteHandle(Handle);
  2415.         }
  2416.  
  2417.         return(Flags);
  2418.     }
  2419.     else
  2420.         return(NULL);
  2421. }
  2422.  
  2423.     /* xpr_unlink(STRPTR FileName):
  2424.      *
  2425.      *    Remove (delete) a given file.
  2426.      */
  2427.  
  2428. LONG __saveds __asm
  2429. xpr_unlink(register __a0 STRPTR FileName)
  2430. {
  2431.         /* Sorry, but it is far too dangerous to let the protocol
  2432.          * remove any files with path name substitution enabled.
  2433.          * The protocol could accidentally hit the wrong file.
  2434.          */
  2435.  
  2436.     if(!Config -> MiscConfig -> OverridePath)
  2437.     {
  2438.         if(OriginalName[0])
  2439.         {
  2440.             if(!Stricmp(ShrunkenName,FileName))
  2441.                 FileName = OriginalName;
  2442.         }
  2443.  
  2444.         if(DeleteFile(FileName))
  2445.         {
  2446.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  2447.  
  2448.             return(0);
  2449.         }
  2450.     }
  2451.  
  2452.     return(-1);
  2453. }
  2454.  
  2455.     /* xpr_squery():
  2456.      *
  2457.      *    Check how many characters are present in the serial buffer.
  2458.      */
  2459.  
  2460. LONG __saveds __asm
  2461. xpr_squery()
  2462. {
  2463.     if(WriteRequest)
  2464.     {
  2465.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  2466.  
  2467.         DoIO(WriteRequest);
  2468.  
  2469.             /* Return error if carrier is lost. */
  2470.  
  2471.         if((WriteRequest -> io_Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier)
  2472.         {
  2473.             if(!CarrierMessage)
  2474.             {
  2475.                 CarrierMessage = TRUE;
  2476.  
  2477.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  2478.             }
  2479.  
  2480.             Online = FALSE;
  2481.  
  2482.             TransferError = TRUE;
  2483.         }
  2484.         else
  2485.             return((LONG)WriteRequest -> IOSer . io_Actual);
  2486.     }
  2487.  
  2488.     return(-1);
  2489. }
  2490.  
  2491.     /* xpr_getptr(LONG InfoType):
  2492.      *
  2493.      *    Return a pointer to the term custom screen.
  2494.      */
  2495.  
  2496. LONG __saveds __asm
  2497. xpr_getptr(register __d0 LONG InfoType)
  2498. {
  2499.     if(InfoType == 1)
  2500.         return((LONG)Window -> WScreen);
  2501.     else
  2502.         return(-1);
  2503. }
  2504.  
  2505.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  2506.      *
  2507.      *    Steal the contents of the options buffer (replacement
  2508.      *    for xpr_gets).
  2509.      */
  2510.  
  2511. LONG __saveds __asm
  2512. xpr_stealopts(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  2513. {
  2514.     if(Buffer)
  2515.         strcpy(ProtocolOptsBuffer,Buffer);
  2516.  
  2517.     return(1);
  2518. }
  2519.